package com.wxb.springcloudgateway;

import com.wxb.apiclientsdk.utils.SignUtils;
import com.wxb.common.model.entity.InterfaceInfo;
import com.wxb.common.model.entity.User;
import com.wxb.common.service.InnerInterfaceInfoService;
import com.wxb.common.service.InnerUserInterfaceService;
import com.wxb.common.service.InnerUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

/**
 * 全局过滤
 */
@Slf4j
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @DubboReference
    private InnerUserService innerUserService;

    @DubboReference
    private InnerUserInterfaceService innerUserInterfaceService;

    @DubboReference
    private InnerInterfaceInfoService innerInterfaceInfoService;

    private static final List<String> IP_WHITE_LIST = Arrays.asList("127.0.0.1","0:0:0:0:0:0:0:1");
    //private static final String INTERFACE_HOST = "http://localhost:8004";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //1.请求日志
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();
        String method = request.getMethod().toString();
        log.info("请求的唯一标识" + request.getId());
        log.info("请求路径" + path);
        log.info("请求方法" + method);
        log.info("请求参数" + request.getQueryParams());
        String sourceAddress = request.getLocalAddress().getHostString();
        log.info("请求来源地址" + sourceAddress);
        log.info("请求的来源地址" + request.getRemoteAddress().getHostString());
        ServerHttpResponse response = exchange.getResponse();
        //2.黑白名单
        if (!IP_WHITE_LIST.contains(sourceAddress)){
            return handleNoAuth(response);
        }
        //3.用户鉴权
        HttpHeaders headers = request.getHeaders();
        String accessKey = headers.getFirst("accessKey");
        String nonce = headers.getFirst("nonce");
        String timestamp = headers.getFirst("timestamp");
        String sign = headers.getFirst("sign");
        String body = headers.getFirst("body");
        User user = new User();
        user = null;
        try {
            user = innerUserService.getInvokeUser(accessKey);
        }catch (Exception e){
            log.error("获取用户失败" + e);
        }
        if (user == null){
            return handleNoAuth(response);
        }

        if (Long.parseLong(nonce) > 10000L){
            return handleNoAuth(response);
        }
        Long currentTime = System.currentTimeMillis() /1000;
        final Long FIVE_MINUTES = 60 * 5L;
        if ((currentTime - Long.parseLong(timestamp) >= FIVE_MINUTES)){
            return handleNoAuth(response);
        }
        String secretKey = user.getSecretKey();
        String serverSign = SignUtils.genSign(body, secretKey);
        if (sign==null || !sign.equals(serverSign)){
            return handleNoAuth(response);
        }
        //4.请求模拟接口是否存在
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        interfaceInfo = null;
        try {
            interfaceInfo = innerInterfaceInfoService.getInterfaceInfo(path, method);
        }catch (Exception e){
            log.error("获取接口失败");
        }
        if (interfaceInfo == null){
            return handleNoAuth(response);
        }
        //5.请求转发
        Mono<Void> filter = chain.filter(exchange);
        //6.调用成功 调用次数加一
        try {
            innerUserInterfaceService.invokeCount(interfaceInfo.getId(),user.getId());
        } catch (Exception e) {
            log.error("调用次数失败" + e);
        }

        if (response.getStatusCode() == HttpStatus.OK){

        }else {
            //7.调用失败返回规范错误码
            return handleInvokeError(response);
        }
        log.info("custom global filter");
        return filter;
    }

    @Override
    public int getOrder() {
        return -1;
    }

    public Mono<Void> handleNoAuth(ServerHttpResponse response){
        response.setStatusCode(HttpStatus.FORBIDDEN);
        return response.setComplete();
    }
    public Mono<Void> handleInvokeError(ServerHttpResponse response){
        response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        return response.setComplete();
    }
}

